package org.jeecg.common.mybatis;

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.reflection.MetaObject;
import org.jeecg.common.properties.config.JeecgPropertyConfig;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * 单数据源配置（jeecg.datasource.open = false时生效）
 *
 * @Author zhoujf
 */
@Configuration
@MapperScan(value = {"org.jeecg.modules.**.mapper*", "org.jeecg.common.**.mapper*"})
public class MybatisPlusConfig {

    /**
     * tenant_id 字段名
     */
    public static final String tenant_field = "company_id";

    @Autowired
    private JeecgPropertyConfig jeecgPropertyConfig;

    /**
     * 有哪些表需要做多租户 这些表需要添加一个字段 ，字段名和tenant_field对应的值一样
     */
    private static final List<String> tenantTable = new ArrayList<String>();
    /**
     * 关键字 判断走多租户的sql过滤
     */
    private static final List<String> CONTAIN_KEYWORD = new ArrayList<String>();

    /**
     * 关键字 判断不走多租户的sql过滤
     */
    private static final List<String> EXCLUDE_KEYWORD = new ArrayList<String>();

    static {
        tenantTable.add("act_z_business");
        tenantTable.add("act_z_node");
        tenantTable.add("act_z_process");
        tenantTable.add("oa_message");
        tenantTable.add("oa_pending");
        tenantTable.add("sys_announcement");
        tenantTable.add("sys_announcement_send");
//        tenantTable.add("sys_category");
//        tenantTable.add("sys_check_rule");
//        tenantTable.add("sys_config");
        tenantTable.add("sys_data_log");
        tenantTable.add("sys_data_source");
//        tenantTable.add("sys_depart");
//        tenantTable.add("sys_depart_role");
//        tenantTable.add("sys_dict");
//        tenantTable.add("sys_dict_item");
        tenantTable.add("sys_encoding_rules");
        tenantTable.add("sys_fill_rule");
        tenantTable.add("sys_log");
//        tenantTable.add("sys_permission");
//        tenantTable.add("sys_permission_data_rule");
//        tenantTable.add("sys_position");
//        tenantTable.add("sys_quartz_job");
//        tenantTable.add("sys_role");
//        tenantTable.add("sys_role_permission");
//        tenantTable.add("sys_sms");
//        tenantTable.add("sys_sms_template");
        tenantTable.add("sys_user");
        tenantTable.add("sys_user_agent");
//        tenantTable.add("sys_user_depart");
//        tenantTable.add("sys_user_role");
//        tenantTable.add("zcgl_asset_image");
        tenantTable.add("zcgl_asset_info");
        tenantTable.add("zcgl_asset_info_sub");
        tenantTable.add("zcgl_attention_info");
//        tenantTable.add("zcgl_customer_attention");
//        tenantTable.add("zcgl_customer_info");
        tenantTable.add("zcgl_lease_contract_content");
        tenantTable.add("zcgl_lease_contract_info");
        tenantTable.add("zcgl_lease_contract_standard_rent");
        tenantTable.add("zcgl_order");
        tenantTable.add("zcgl_order_details");
        tenantTable.add("zcgl_payables_details");
        tenantTable.add("zcgl_payables_info");
        tenantTable.add("zcgl_public_account_transaction_inquiry");
        tenantTable.add("zcgl_public_account_transaction_inquiry_details");
        tenantTable.add("zcgl_receivables_info");
//        tenantTable.add("zcgl_region");
//        tenantTable.add("zcgl_region_user");
        tenantTable.add("zcgl_remind_log");
        tenantTable.add("zcgl_repair_feedback_log");
//        tenantTable.add("zcgl_repair_image");
        tenantTable.add("zcgl_repair_info");
        tenantTable.add("zcgl_statement_account");
        tenantTable.add("zcgl_statement_account_details");


        EXCLUDE_KEYWORD.add("sys_depart where org_code");
        EXCLUDE_KEYWORD.add("* from  sys_user  where username =");
        EXCLUDE_KEYWORD.add("like concat(org_code,");


        CONTAIN_KEYWORD.add("select");
    }
    @Bean
    public OptimisticLockerInterceptor OptimisticLockerInnerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    /**
     * 多租户属于 SQL 解析部分，依赖 MP 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor().setLimit(-1);
        //多租户配置 配置后每次执行sql会走一遍他的转化器 如果不需要多租户功能 可以将其注释
        tenantConfig(paginationInterceptor);
//        paginationInterceptor.setp
        return paginationInterceptor;
    }

    /**
     * 多租户的配置
     *
     * @param paginationInterceptor
     */
    private void tenantConfig(PaginationInterceptor paginationInterceptor) {
        /*
         * 【测试多租户】 SQL 解析处理拦截器<br>
         * 这里固定写成住户 1 实际情况你可以从cookie读取，因此数据看不到 【 麻花藤 】 这条记录（ 注意观察 SQL ）<br>
         */
        List<ISqlParser> sqlParserList = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new JeecgTenantParser();
        tenantSqlParser.setTenantHandler(new TenantHandler() {

            @Override
            public Expression getTenantId(boolean select) {
                LoginUser loginUser = JwtUtil.getLoginUser();
                if (loginUser != null) {
                    return new LongValue(loginUser.getCurrentCompanyId());
                }
                return new LongValue(1);
            }

            @Override
            public String getTenantIdColumn() {
                return tenant_field;
            }

            @Override
            public boolean doTableFilter(String tableName) {
                //true则不加租户条件查询  false则加
                // return excludeTable.contains(tableName);
//                LoginUser loginUser = JwtUtil.getLoginUser();
//                if (loginUser != null && tenantTable.contains(tableName)) {
//                    if (jeecgPropertyConfig.getBaseDepartId().equalsIgnoreCase(loginUser.getCurrentCompanyId())) {
//                        return true;
//                    }
//                    return false;
//                }
                return true;
            }

//            private Expression in(String ids) {
//                final InExpression inExpression = new InExpression();
//                inExpression.setLeftExpression(new Column(getTenantIdColumn()));
//                final ExpressionList itemsList = new ExpressionList();
//                final List<Expression> inValues = new ArrayList<>(2);
//                for (String id : ids.split(CommonConstant.DEFAULT_SEPARATOR)) {
//                    inValues.add(new LongValue(id));
//                }
//                itemsList.setExpressions(inValues);
//                inExpression.setRightItemsList(itemsList);
//                return inExpression;
//            }

        });

        sqlParserList.add(tenantSqlParser);
        paginationInterceptor.setSqlParserList(sqlParserList);
        paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
            @Override
            public boolean doFilter(MetaObject metaObject) {
                String sql = (String) metaObject.getValue(PluginUtils.DELEGATE_BOUNDSQL_SQL);
                String sql_lowercase = sql.toLowerCase();
                for (String key : EXCLUDE_KEYWORD) {
                    if (sql_lowercase.indexOf(key) >= 0) {
                        return true;
                    }
                }

                for (String tableName : tenantTable) {
                    if (sql_lowercase.indexOf(tableName.toLowerCase()) >= 0) {
                        for (String key : CONTAIN_KEYWORD) {
                            if (sql_lowercase.indexOf(key) >= 0) {
                                return false;
                            }
                        }
                        return true;
                    }
                }
                /*if ("mapper路径.方法名".equals(ms.getId())) {
                    //使用这种判断也可以避免走此过滤器
                    return true;
                }*/
                return true;
            }
        });
    }
//    /**
//     * mybatis-plus SQL执行效率插件【生产环境可以关闭】
//     */
//    @Bean
//    public PerformanceInterceptor performanceInterceptor() {
//        return new PerformanceInterceptor();
//    }


}
